/*
	This file is part of AVRCppLib.

    AVRCppLib is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AVRCppLib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AVRCppLib.  If not, see <http://www.gnu.org/licenses/>.

    Copyright (C) Maxime Lemonnier 2007-2011
 */

#ifndef Comparator_H_
#define Comparator_H_

#include "../Utils/CppExtensions.h"
#include "../Utils/BitManipulation.h"
#include "../CallbackServers/CallbackConnector.h"
#include "TimerOutputCompareModes.h"

namespace Timers
{
using CompareModes::CompareMode;

template <typename IOAddressType, typename uint_t>
class Comparator :  public CallbackConnector
{
public:
	Comparator(uint8_t callbackVectorNumber, IOAddressType ocr, IOAddress tccra, uint8_t comMask, IOAddress timsk, uint8_t ocie, IOAddress tifr, uint8_t ocf);
	virtual ~Comparator();

	inline void setOCRValue(uint_t value) const FORCE_INLINE;
	inline uint_t getOCRValue() const FORCE_INLINE;
	inline void setOCROutputPinMode(CompareMode mode) const FORCE_INLINE;
	inline void enableOCRInterrupts() const FORCE_INLINE;
	inline void disableOCRInterrupts() const FORCE_INLINE;
	inline bool readOCRFlag() const FORCE_INLINE;
	inline void clearOCRFlag() const FORCE_INLINE;

protected:
	IOAddressType ocr;
	IOAddress tccra;
	uint8_t comMask;
	IOAddress timsk;
	uint8_t ocie;
	IOAddress tifr;
	uint8_t ocf;
};

typedef Comparator<IOAddress, uint8_t> Comparator8;

typedef Comparator<IOAddress16, uint16_t> Comparator16;

template <typename IOAddressType, typename uint_t>
void Comparator<IOAddressType, uint_t>::setOCRValue(uint_t value) const
{
	*ocr = value;
}
template <typename IOAddressType, typename uint_t>
uint_t Comparator<IOAddressType, uint_t>::getOCRValue() const
{
	return *ocr;
}
template <typename IOAddressType, typename uint_t>
void Comparator<IOAddressType, uint_t>::setOCROutputPinMode(CompareMode mode) const
{
	setConfig(tccra, comMask, mode);
}

template <typename IOAddressType, typename uint_t>
void Comparator<IOAddressType, uint_t>::enableOCRInterrupts() const
{
	setBit(*timsk, ocie);
}

template <typename IOAddressType, typename uint_t>
void Comparator<IOAddressType, uint_t>::disableOCRInterrupts() const
{
	clearBit(*timsk, ocie);
}

template <typename IOAddressType, typename uint_t>
bool Comparator<IOAddressType, uint_t>::readOCRFlag() const
{
	return bitIsSetInRegister(*tifr, ocf);
}

template <typename IOAddressType, typename uint_t>
void Comparator<IOAddressType, uint_t>::clearOCRFlag() const
{
	setBit(*tifr, ocf);
}

}

#endif /* Comparator_H_ */
